package com.vipboot.platform.system.crud.service.rbac;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vipboot.framework.core.exception.ServiceException;
import com.vipboot.framework.core.util.AssertCheck;
import com.vipboot.framework.core.util.MapStructUtil;
import com.vipboot.framework.mybatisplus.core.page.PageData;
import com.vipboot.framework.mybatisplus.core.page.PageQuery;
import com.vipboot.platform.system.crud.dao.SysClientDao;
import com.vipboot.platform.system.domain.bo.SysClientBo;
import com.vipboot.platform.system.domain.entity.SysClient;
import com.vipboot.platform.system.domain.vo.SysClientVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class SysClientService {
    private final SysClientDao sysClientDao;

    private LambdaQueryWrapper<SysClient> buildQueryWrapper(SysClientBo bo) {
        LambdaQueryWrapper<SysClient> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getClientId()), SysClient::getClientId, bo.getClientId());
        lqw.eq(StrUtil.isNotBlank(bo.getClientKey()), SysClient::getClientKey, bo.getClientKey());
        lqw.eq(StrUtil.isNotBlank(bo.getClientSecret()), SysClient::getClientSecret, bo.getClientSecret());
        lqw.eq(StrUtil.isNotBlank(bo.getStatus()), SysClient::getStatus, bo.getStatus());
        lqw.orderByAsc(SysClient::getCreateTime);
        return lqw;
    }

    /**
     * 分页查询
     */
    public PageData<SysClientVo> page(SysClientBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysClient> lqw = this.buildQueryWrapper(bo);
        Page<SysClientVo> page = sysClientDao.pageVo(pageQuery.build(), lqw, SysClientVo.class);
        page.getRecords().forEach(it -> it.setGrantTypeList(List.of(it.getGrantType().split(","))));
        return PageData.build(page);
    }

    /**
     * 保存
     */
    public boolean save(SysClientBo bo) {

        if (this.checkExistClientKey(bo.getClientKey())) {
            throw new ServiceException(bo.getClientKey() + " 客户端Key已存在");
        }

        SysClient entity = MapStructUtil.convert(bo, SysClient.class);
        entity.setGrantType(String.join(",", bo.getGrantTypeList()));
        // 生成 clientId
        String clientKey = bo.getClientKey();
        String clientSecret = bo.getClientSecret();
        entity.setClientId(SecureUtil.md5(clientKey + clientSecret));
        return sysClientDao.save(entity);
    }

    /**
     * 更新
     */
    public boolean update(SysClientBo bo) {
        if (this.checkExistClientKey(bo.getClientKey())) {
            throw new ServiceException(bo.getClientKey() + " 客户端Key已存在");
        }

        SysClient entity = MapStructUtil.convert(bo, SysClient.class);
        entity.setGrantType(String.join(",", bo.getGrantTypeList()));
        return sysClientDao.updateById(entity);
    }

    /**
     * 删除单条
     */
    public boolean removeById(Long id) {
        return sysClientDao.removeById(id);
    }

    /**
     * 更改状态
     */
    public boolean changeStatus(String clientId, String status) {
        AssertCheck.throwIfNull(clientId, "ID不能为空");
        LambdaUpdateWrapper<SysClient> lqw = Wrappers.lambdaUpdate();
        lqw.set(SysClient::getStatus, status);
        lqw.eq(SysClient::getClientId, clientId);
        return sysClientDao.update(lqw);
    }


    public SysClientVo getByClientId(String clientId) {
        LambdaQueryWrapper<SysClient> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysClient::getClientId, clientId);
        SysClient client = sysClientDao.getOne(lqw);
        return MapStructUtil.convert(client, SysClientVo.class);
    }


    private boolean checkExistClientKey(String clientKey) {
        LambdaQueryWrapper<SysClient> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(clientKey), SysClient::getClientKey, clientKey);
        return sysClientDao.exists(lqw);
    }
}
